package com.tttshaoqi.aop;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.tttshaoqi.common.constant.RedisConstants;
import com.tttshaoqi.pojo.dto.EmployeeDTO;
import com.tttshaoqi.pojo.entity.Employee;
import com.tttshaoqi.pojo.entity.OperateLog;
import com.tttshaoqi.server.mapper.OperateLogMapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Map;

/**
 * @author tttshaoqi
 * &#064;create 2025-08-01-16:09
 */
@Aspect
@Component
@Slf4j
public class LogAspect {

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private StringRedisTemplate  stringRedisTemplate;

    @Autowired
    private OperateLogMapper  operateLogMapper;

    @Before("pointCut()")
    public void logBefore(){
        log.info("正在记录日志。。。");
    }

    // 设置一个切入点
    @Pointcut("@annotation(com.tttshaoqi.annotation.Log)")
    public void pointCut() {
    }

    @Around("pointCut()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable{
        OperateLog operateLog = new OperateLog();
        // 操作用户id
        String token = request.getHeader("token");
        String key = RedisConstants.LOGIN_USER_KEY + token;
        Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);
        EmployeeDTO user = BeanUtil.fillBeanWithMap(userMap, new EmployeeDTO(), false);
        Long userId = user.getId();
        operateLog.setOperateUser(Math.toIntExact(userId));
        // 操作时间
        LocalDateTime localDateTime = LocalDateTime.now();
        operateLog.setOperateTime(localDateTime);
        // 类名
        String className = joinPoint.getTarget().getClass().getName();
        operateLog.setClassName(className);
        // 方法名
        String methodName = joinPoint.getSignature().getName();
        operateLog.setMethodName(methodName);
        // 方法参数
        Object[] args = joinPoint.getArgs();
        operateLog.setMethodParams(JSONUtil.toJsonStr(args));
        // 计算耗时
        long begin = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long end = System.currentTimeMillis();
        String resultStr = JSONUtil.toJsonStr(result);
        // 返回值
        operateLog.setReturnValue(resultStr);
        // 耗时
        Long costTime = end - begin;
        operateLog.setCostTime(costTime);
        // 记录日志
        operateLogMapper.insert(operateLog);

        return result;
    }

    @After("pointCut()")
    public void logAfter(){
        log.info("日志记录完毕...");
    }

}
